from os import popen, system
from posix import getlogin
import os

system("mkdir -p build")

# generate the setpaths.sh file
def createSetPaths(target, source, env):
	try:
		setPathsSource = open(str(source[0]), "r").read()
		setPathsFile = open(str(target[0]), "w")
		setPathsFile.write(setPathsSource % (prefix))
		setPathsFile.close()
		os.chmod(str(target[0]), 0755)
		print "\nAt this point if the APR headers are still not found you should put:\n\n"
		print "\tsource %s\n\n" % (str(target[0]))
		print "in your environment rc scripts (e.g. ~/.bashrc) and then open a new shell before running scons again.\n"
		return 0
	except:
		raise "Probably can't open target for writing. At this point if the APR headers are still not found it is because apr-1-config cannot be found in the path. Creation of setpaths.sh is necessary for paths to be properly set in your environment.See optional part of INSTALL_README for why setpaths.sh may be important for your installation.\n" % (target)


# generate the top part of the mpiTest.pl file, the rest is concatenated with the source below
def createMpiTest():
	try:
		sourcePrefix = os.path.join(Dir('.').abspath,'src/test')
		testPrefix = os.path.join(prefix, 'tests')
		mpiTestFile = open("build/mpiTest.pl", "w")
		mpiTestFile.write("#!/usr/bin/perl\n\n")
		mpiTestFile.write("# Root directory of where the source directories can be found and where the $dirFile is located.\n")
		mpiTestFile.write("my $sourcePrefix = \"%s\";\n" % (sourcePrefix))
		mpiTestFile.write("# Where to dump the tests\n")
		mpiTestFile.write("my $testPrefix = \"%s\";\n\n" % (testPrefix))
		mpiTestFile.write("### Don't modify below unless you know what you are doing. ###\n\n")
		mpiTestFile.close()
	except:
		print "\nCan't build the mpiTest.pl script. The testing suite will be broken!\n\n"
		raise

# set build directory
BuildDir('build', 'src')

# get install prefix
prefix = ARGUMENTS.get('PREFIX', '/sandbox/%s/mpimt' % getlogin())

# get apr flags
env = Environment()

# check for apr headers
conf = Configure(env)

env.ParseConfig('apr-1-config --cflags --cppflags --includes')
env.ParseConfig('apr-1-config --link-ld --libs')
#env.ParseConfig('%s/bin/apr-1-config --cflags --cppflags --includes' % (prefix))
#env.ParseConfig('%s/bin/apr-1-config --link-ld --libs' % (prefix))

apr_headers = ['apr_general.h', 'apr_pools.h', 'apr_network_io.h', 
               'apr_file_io.h', 'apr_strings.h', 'apr_tables.h']

for file in apr_headers:
  if not conf.CheckCHeader(file):
    print '%s not found... building apr' % (file)
    system("cd apr && ./configure --prefix=%s && make && make install" % (prefix)) 
    # generate the setpaths.sh file
    #createSetPaths()
    #system("cp build/setpaths.sh %s/" % (prefix))

    env.ParseConfig('%s/bin/apr-1-config --cflags --includes' % (prefix))
    env.ParseConfig('%s/bin/apr-1-config --link-ld --libs' % (prefix))

    if not conf.CheckCHeader(file):
      print '%s STILL not found... check the apr build log' % (file)
      Exit(0)

if not conf.CheckLib('apr-1'):
  print 'libapr-1.a or libapr-1.so not found'
  Exit(1)

if not conf.CheckLib('pthread'):
  print 'libpthread.a or libpthread.so not found'
  Exit(1)
	
env = conf.Finish()

library_files = ['build/cm.c', 'build/log.c', 'build/msg.c', 'build/oom.c',
                 'build/pmi_simple.c', 'build/uid.c', 'build/util.c',
                 'build/coll.c', 'build/comm.c', 'build/dtypes.c',
                 'build/env.c',  'build/pt2pt.c', 'build/oper.c', 'build/topology.c']

# build static libmpi.a
static_lib = env.StaticLibrary('build/libmpi', library_files)

# build shared libmpi.so
shared_lib = env.SharedLibrary('build/libmpi', library_files)

# create an environment for building the test programs
test_env = env.Copy()
test_env.Append(CPPPATH='build')
test_env.Append(LIBPATH='build')
test_env.Append(LIBS='mpi')

# other stuff that should go in bin
bin_programs = []
bin_programs.append('build/mpimtcc')
bin_programs.append('build/mpiTest.pl')

# grab the prefix and put it in the mpimtcc script
# SCons makes a hardlink between files in build and src so it's necessary to name the src something different if you don't want it overwritten when you are modiyfing it.
targetFile = open('build/mpimtcc','w')
targetFile.write("#!/bin/sh\n\n")
targetFile.write("PREFIX=%s\n\n" % (prefix))
sourceFile = open('src/mpimtcc.sh.src','r')
targetFile.write(sourceFile.read())
targetFile.close()
sourceFile.close()


# do the same for the mpiTest.pl script
createMpiTest()
targetFile = open('build/mpiTest.pl', 'a')
sourceFile = open('src/mpiTest.pl.src','r')
targetFile.write(sourceFile.read())
targetFile.close()
sourceFile.close()

for file in bin_programs:
	Execute(Chmod(file, 0755))

# keep test program objects in a list to install them later
test_programs = []
test_programs.append(test_env.Program('build/test/basic/test_init.c'))
test_programs.append(test_env.Program('build/test/coll/test_allgather.c'))
test_programs.append(test_env.Program('build/test/coll/test_alltoall.c'))
test_programs.append(test_env.Program('build/test/coll/test_barrier.c'))
test_programs.append(test_env.Program('build/test/coll/test_bcast.c'))
test_programs.append(test_env.Program('build/test/coll/test_gather.c'))
test_programs.append(test_env.Program('build/test/coll/test_gatherv.c'))
test_programs.append(test_env.Program('build/test/coll/test_reduce.c'))
test_programs.append(test_env.Program('build/test/coll/test_opcreate.c'))
test_programs.append(test_env.Program('build/test/coll/test_allreduce.c'))
test_programs.append(test_env.Program('build/test/coll/test_ping.c'))
test_programs.append(test_env.Program('build/test/coll/test_pingpongLAM.c'))
#test_programs.append(test_env.Program('build/test/coll/test_prime.c'))
test_programs.append(test_env.Program('build/test/coll/test_scatter.c'))
test_programs.append(test_env.Program('build/test/coll/test_scatterv.c'))
#test_programs.append(test_env.Program('build/test/coll/test_sr.c'))
test_programs.append(test_env.Program('build/test/dtypes/test_type_contig.c'))
test_programs.append(test_env.Program('build/test/dtypes/test_type_hindex.c'))
test_programs.append(test_env.Program('build/test/dtypes/test_type_hvect.c'))
test_programs.append(test_env.Program('build/test/dtypes/test_type_index.c'))
test_programs.append(test_env.Program('build/test/dtypes/test_type_struct.c'))
test_programs.append(test_env.Program('build/test/dtypes/test_type_vect.c'))
test_programs.append(test_env.Program('build/test/dtypes/test_type_complex.c'))
test_programs.append(test_env.Program('build/test/dtypes/test_get_elements.c'))
test_programs.append(test_env.Program('build/test/dtypes/test_pack_size.c'))
test_programs.append(test_env.Program('build/test/dtypes/test_pack_basic.c'))
test_programs.append(test_env.Program('build/test/dtypes/test_pack_derived.c'))
test_programs.append(test_env.Program('build/test/dtypes/test_send_packed.c'))
test_programs.append(test_env.Program('build/test/dtypes/test_send_contig.c'))
test_programs.append(test_env.Program('build/test/pt2pt/modified_sendrcvtest.c'))
test_programs.append(test_env.Program('build/test/pt2pt/test_get_count.c'))
test_programs.append(test_env.Program('build/test/pt2pt/test_sendrecv.c'))
test_programs.append(test_env.Program('build/test/pt2pt/test_hang.c'))
test_programs.append(test_env.Program('build/test/pt2pt/test_test.c'))
test_programs.append(test_env.Program('build/test/pt2pt/test_nqueens.c'))
test_programs.append(test_env.Program('build/test/pt2pt/test_probe.c'))
test_programs.append(test_env.Program('build/test/pt2pt/test_recvfirst.c'))
test_programs.append(test_env.Program('build/test/pt2pt/test_sendfirst.c'))
test_programs.append(test_env.Program('build/test/pt2pt/test_sendrecv.c'))
test_programs.append(test_env.Program('build/test/pt2pt/test_sr.c'))
#test_programs.append(test_env.Program('build/test/pt2pt/test_start.c'))
test_programs.append(test_env.Program('build/test/pt2pt/test_waitall.c'))
test_programs.append(test_env.Program('build/test/pt2pt/test_waitsome.c'))
test_programs.append(test_env.Program('build/test/group/test_comm_create.c'))
test_programs.append(test_env.Program('build/test/group/test_comm_dup.c'))
test_programs.append(test_env.Program('build/test/group/test_group_incl.c'))
test_programs.append(test_env.Program('build/test/group/test_group_translate_ranks.c'))
test_programs.append(test_env.Program('build/test/topo/topo_test.c'))
env.Alias('tests', test_programs)

# base files
base_files = []
base_files.append('build/setpaths.sh')

#other scripts
setpaths = Builder(action = createSetPaths)
env.Append(BUILDERS = {'setpaths': setpaths})
env.setpaths('build/setpaths.sh', 'bin/setpaths.in')
#bin_programs.append(env.setpaths)

# install target
lib = env.Install("%s/lib" % (prefix), [static_lib, shared_lib])
tests = env.Install("%s/test" % (prefix), test_programs)
include = env.Install("%s/include" % (prefix), 'build/mpi.h')

bin = env.Install("%s/bin" % (prefix), bin_programs)
base = env.Install("%s" % (prefix), base_files)
env.Alias('install', [lib, tests, include, bin, base])
